/** sps_main.cpp - the program entry point
 *
 * This file includes the program entry point.
 *
 */

/**< The type of service will running */
static int optype;

#define DB_FILE_NAME            "spserv.db"

#define SPS_RUN_SERVICE          1
#define SPS_INSTALL_SERVICE      2
#define SPS_UNINSTALL_SERVICE    3
#define SPS_START_SERVICE        4
#define SPS_STOP_SERVICE         5
#define SPS_SHOW_HELP            6
 
#include "sps_config.h"

/**< The database file name for sign proxy service */
std::string sps_db_name;

/** @brief Get the options of the program
 *  @param argc [in] The number of parameters of program
 *  @param argc [in] The array of parameters of program
 *  @return If no errors, zero is returned. Otherwise, non-zero is returned
 */
static int GetOptions(int argc, char **argv)
{
  if (argc > 2) {
    optype = SPS_SHOW_HELP;
    return 1;
  }

  if (argc == 1) {
    optype = SPS_RUN_SERVICE;
  } else {
    char *p = argv[1];
    if (strcmp(p, "-i") == 0 || strcmp(p, "--install") == 0) {
      optype = SPS_INSTALL_SERVICE;
      
    } else if (strcmp(p, "-u") == 0 || strcmp(p, "--uninstall") == 0) {
      optype = SPS_UNINSTALL_SERVICE;
      
    } else if (strcmp(p, "-s") == 0 || strcmp(p, "--start") == 0) {
      optype = SPS_START_SERVICE;
      
    } else if (strcmp(p, "-t") == 0 || strcmp(p, "-stop") == 0) {
      optype = SPS_STOP_SERVICE;
      
    } else if (strcmp(p, "-h") == 0 || strcmp(p, "-help") == 0) {
      optype = SPS_SHOW_HELP;
      
    } else {
      std::cerr <<"SignProxyService: invalid option " <<p <<std::endl;
      return 1;
    }
  }
  
  return 0;
}

static void Usage()
{
  std::cerr <<std::endl;
  std::cerr <<"Usage: SignProxyService [option]"         <<std::endl;
  std::cerr <<std::endl;
  std::cerr <<"Options:" <<std::endl;
  std::cerr <<"  -h, --help          : show this page"    <<std::endl;
  std::cerr <<std::endl;
  std::cerr <<"  -i, --install       : install service"   <<std::endl;
  std::cerr <<"  -u, --uninstall     : unistall service"  <<std::endl;
  std::cerr <<"  -s, --start         : start service"     <<std::endl;
  std::cerr <<"  -t, --stop          : stop service"      <<std::endl;
  std::cerr <<std::endl;
}

/** @brief Initialize SignProxyService
 *  @param argc [in] The number of parameters of program
 *  @param argv [in] The array of parameters of program
 *  @return If no errors, zero is returned. Otherwise, -1 is returned
 */
static int InitProgram(int argc, char **argv)
{
  int    ret;
  char  *p;
  char   file[1024];
  size_t len;

  p = (char *)strrchr(argv[0], '\\');
  if (p == NULL) {
    memcpy(file, DB_FILE_NAME, sizeof(DB_FILE_NAME));
  } else {
    len = (size_t)(p - argv[0] + 1);
    memcpy(file, argv[0], len);
    memcpy(file + len, DB_FILE_NAME, sizeof(DB_FILE_NAME));
  }
  sps_db_name = str2utf8(file);

  ret = GetOptions(argc, argv);
  if (ret || optype == SPS_SHOW_HELP) {
    Usage();
    return -1;
  }

  /* Only in SPS_RUN_SERVICE state, we use the log file. */
  if (optype == SPS_RUN_SERVICE) {
    if (SpsLog::instance().openLog(argv[0]) == false) {
      std::cerr <<"initialize log file failed" <<std::endl;
      return -1;
    }

    WORD ver;
    WSADATA wsadata;

    ver = MAKEWORD(2, 2);
    int err = WSAStartup(ver, &wsadata);
    if (err) {
      SpsLog::instance().logEmerg("initialize windows socket failed");
      return -1;
    }
  }
  
  return 0;
}

/** @brief Clear SignProxyService resource
 */
static void ExitProgram()
{
  if (optype == SPS_RUN_SERVICE) {
    int err = WSACleanup();
    if (err) {
      SpsLog::instance().logEmerg("clean up windows socket failed (%d)",
				  WSAGetLastError());
    }
    SpsLog::instance().logDebug("exit the program");
    SpsLog::instance().closeLog();
  }
}

int main(int argc, char **argv)
{
  int        ret = 0;
  SpsService serv;
  
  ret = InitProgram(argc, argv);
  if (ret == -1) {
    return 1;
  }

  switch (optype) {

  case SPS_RUN_SERVICE:
    ret = serv.runService();
    break;

  case SPS_INSTALL_SERVICE:
    ret = serv.installService();
    break;

  case SPS_UNINSTALL_SERVICE:
    ret = serv.uninstallService();
    break;

  case SPS_START_SERVICE:
    ret = serv.startService();
    SpsLog::instance().logInfo("start sign proxy service");
    break;

  case SPS_STOP_SERVICE:
    ret = serv.stopService();
    SpsLog::instance().logInfo("stop sign proxy service");
    break;

  default:
    /* never reached here */
    SpsLog::instance().logStderr("Invalid operation type");
    break;
  }

  ExitProgram();
  
  return ret;
}
